package com.webbdong.aop.agent.test.bytebuddy;


import net.bytebuddy.asm.Advice;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * Created by yuan on 2018/7/29.
 */

/**
 * 注意：实例方法使用@Advice.This注解，静态方法使用@Advice.Origin 两者不能混用
 */
public class ThreadPoolAdviceInterceptor {

    //.defineField("threadPools",Set.class, Visibility.PUBLIC, Ownership.STATIC, FieldManifestation.FINAL);
    @Advice.OnMethodEnter()
    public static void enter(@Advice.This Object object,
                             @Advice.FieldValue(value = "threadPools", readOnly = false) Map<Object, Object> threadPools) {
        try {
            if (threadPools != null && threadPools.containsKey(object)){
                return;
            }
            if (object instanceof ThreadPoolExecutor) {
                if (threadPools == null) {
                    synchronized (ThreadPoolExecutor.class) {
                        if (threadPools == null) {
                            threadPools = new ConcurrentHashMap<>();
                        }
                    }
                }
                String threadName = "";
                Method getThreadFactory = object.getClass().getMethod("getThreadFactory");
                Object threadFactory = getThreadFactory.invoke(object);
                Field[] fields = threadFactory.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.getType().equals(String.class) && field.getName().contains("name")) {
                        field.setAccessible(true);
                        threadName = (String) field.get(threadFactory);
                    }
                }
                threadPools.put(object, threadName);
            }
        } catch (Exception e) {

        }
    }




}
